package tpanalisis.main.java;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Clase orientada al manejo de los archivos (busqueda, lectura, etc).<br />
 * Esta clase es un singleton (no necesita ser instanceada), para obtener una
 * instancia de ella basta con poner FileUtils.getInstance();
 * 
 * @author cgaggino
 * 
 */
public class FileUtils {

	private static FileUtils instance = null;

	private FileUtils() {
	}

	public static FileUtils getInstance() {
		if (instance == null) {
			instance = new FileUtils();
		}
		return instance;
	}

	/**
	 * Metodo para obtener todos los archivos .java de un directorio
	 * (recursivamente).
	 * 
	 * @param path
	 *            ruta raiz que contiene el source del proyecto.
	 * @return lista de archivos .java del directorio raiz pasado por
	 *         parametros.
	 */
	public List<String> getArchivosFuente(String path) {

		List<String> archivosJava = new ArrayList<String>();
		File directorio = new File(path);
		String[] archivos = directorio.list();
		for (String archivo : archivos) {
			if (!archivo.contains(".")) {
				archivosJava.addAll(getArchivosFuente(path + "/" + archivo));
			}
			if (archivo.contains(".java")) {
				archivosJava.add(path + "/" + archivo);
			}
		}
		return archivosJava;
	}

	/**
	 * Metodo para obtener el codigo de un archivo .java
	 * 
	 * @param path
	 *            ruta del archivo .java
	 * @return lista de string con el contenido del archivo linea por linea
	 *         (codigo del .java).
	 */
	public List<String> getCodigoDeArchivo(String path) {
		List<String> codigo = new ArrayList<String>();
		File archivo = new File(path);
		BufferedReader archivoJava = null;
		try {
			archivoJava = new BufferedReader(new FileReader(archivo));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		String linea = null;
		try {
			while ((linea = archivoJava.readLine()) != null) {
				codigo.add(linea);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return codigo;
	}

	/**
	 * Metodo para obtener todas las funciones a partir del codigo de un archivo
	 * .java
	 * 
	 * @param codigo
	 *            codigo del archivo .java
	 * @return lista de objetos Funcion
	 */
	public List<Funcion> getFunciones(List<String> codigo) {
		List<Funcion> funciones = new ArrayList<Funcion>();
		boolean leerFuncion = false;
		boolean leerJavaDoc = false;
		int llavesAbiertas = 0;
		int llavesCerradas = 0;
		Funcion funcion = new Funcion();
		for (String linea : codigo) {
			if (!leerFuncion && linea.contains("/**")) {
				leerJavaDoc = true;
			}
			if (leerJavaDoc) {
				funcion.addCodigo(linea);
				if (linea.contains("*/")) {
					leerJavaDoc = false;
				}
			}
			String anterior = "";
			if ((linea.contains("public") || linea.contains("private") || linea.contains("protected")) && linea.contains("(") && linea.contains(")")) {
				String[] header = linea.split(" ");
				for (String element : header) {
					if (element.contains("(")) {
						if(element.substring(0, element.indexOf("(")).isEmpty())
							funcion.setNombre(anterior);
						else
							funcion.setNombre(element.substring(0, element.indexOf("(")));
						break;
					}
					anterior = element;
				}
				leerFuncion = true;
			}
			if (leerFuncion) {
				if (linea.contains("{")) {
					llavesAbiertas++;
				}
				if (linea.contains("}")) {
					llavesCerradas++;
				}
				funcion.addCodigo(linea);
				if (llavesAbiertas == llavesCerradas) {
					leerFuncion = false;
					funciones.add(funcion);
					funcion = new Funcion();
				}
			}

		}
		return funciones;
	}
}
